import datetime

from django.db import models
from django.db.models import Sum
from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _

from jiaozi.utils import model_data_from_cache, get_order_code, int_value


order_state_choices = (
        (1, '待付款'),
        (2, '待发货'),
        (3, '待收货'),
        (4, '已收货'),
        (5, '已退款')
    )


class ProductSalesOrder(models.Model):
    order_number = models.CharField(verbose_name=_('订单编号'), max_length=255, null=True, blank=True, unique=True)
    user = models.ForeignKey(
        'app.WxUser',
        on_delete=models.PROTECT,
        verbose_name=_('关联用户')
    )
    address = models.ForeignKey(
        'app.UserAddress',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('地址')
    )
    customer_notes = models.TextField(verbose_name=_('客户备注'), max_length=1000, null=True, blank=True)

    # 订单金额合计
    price_initial = models.DecimalField(
        verbose_name=_('订单原价'), null=True, blank=True, max_digits=12, decimal_places=2)
    price_payed = models.DecimalField(
        verbose_name=_('支付金额'), null=True, blank=True, max_digits=12, decimal_places=2)

    # 订单状态
    is_payed = models.BooleanField(verbose_name='已支付', default=False)
    is_send = models.BooleanField(verbose_name='已发货', default=False)
    is_show = models.BooleanField(verbose_name='是否展示', default=True)

    order_state = models.SmallIntegerField(
        verbose_name=_('订单状态'), null=True, default=1, choices=order_state_choices)
    pay_record = models.ForeignKey(
        'money.PayRecord',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('支付记录')
    )

    logistics_number = models.CharField(verbose_name='物流单号', max_length=255, null=True, blank=True)
    logistics_push = models.IntegerField(verbose_name='物流提醒次数', default=0, null=True, blank=True)

    notes = models.TextField(verbose_name=_('后台备注'), max_length=1000, null=True, blank=True)
    datetime_created = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)

    objects = models.Manager()

    def make_order_number(self):
        if not self.order_number:
            self.order_number = get_order_code()

    def update_order_state(self):
        # 自动更新订单的状态
        if self.is_payed:
            if self.order_state < 2:
                self.order_state = 2
        if self.is_send:
            if self.order_state < 3:
                self.order_state = 3
        if not self.is_show:
            if self.order_state < 5:
                self.order_state = 5
    
    def update_price(self):
        order_items = OrderItem.objects.filter(
            product_sales_order_id=self.pk
        ).values('amount', 'price_initial', 'price_payed')
        price_initial = 0
        price_payed = 0
        for order_item in order_items:
            price_initial += float(order_item.get('price_initial')) * int(order_item.get('amount'))
            price_payed += float(order_item.get('price_payed')) * int(order_item.get('amount'))
        self.price_initial = price_initial
        self.price_payed = price_payed
        self.save()

    def _get_order_items(self):
        from product.models import ProductSales, ProductInfo, ProductBatch
        order_item_list = list(OrderItem.objects.filter(
            product_sales_order_id=self.pk
        ).values('product_sales', 'amount', 'price_initial', 'price_payed', 'vip_level_id'))
        for order_item in order_item_list:
            order_item['product_sales'] = model_data_from_cache(ProductSales, order_item['product_sales'])
            order_item['product_sales']['product_batch'] = model_data_from_cache(
                ProductBatch, order_item['product_sales'].get('product_batch')
            )
            order_item['product_sales']['product_batch']['product_info'] = model_data_from_cache(
                ProductInfo, order_item['product_sales']['product_batch']['product_info']
            )
        return order_item_list

    def _set_order_items(self, order_item_list):
        from product.models import ProductSales
        from product.views import get_user_can_buy_amount
        user_current_week_vip_can_buy, has_bought_product_ids = get_user_can_buy_amount(self.user_id)
        for order_item in order_item_list:
            product_sales = order_item['product_sales']
            update_data = {
                'amount': order_item['amount'],
                'price_initial': order_item['price_initial'],
                'price_payed': order_item['price_payed'],
            }
            # 更新当前购买记录消耗的 vip 兑换次数
            product_sales_info = ProductSales.objects.get(pk=product_sales)
            if product_sales not in has_bought_product_ids:
                vip_level_ids = list(product_sales_info.vip_level.all().values_list('pk', flat=True))
                if vip_level_ids:
                    for c_vip_level_id, c_can_buy_amount in user_current_week_vip_can_buy.items():
                        if c_vip_level_id in vip_level_ids:
                            if c_can_buy_amount:
                                update_data['vip_level_id'] = c_vip_level_id
                                break
            # 获取之前的记录
            filter_data = {
                'product_sales_order_id': self.pk,
                'product_sales_id': product_sales,
            }
            pre_item = OrderItem.objects.filter(**filter_data)
            print('_set_order_items', filter_data, update_data)
            if pre_item.exists():
                if pre_item.count() > 1:
                    pre_item.delete()
                    OrderItem.objects.create(**filter_data, **update_data)
                else:
                    pre_item = pre_item.first()
                    for k, v in update_data.items():
                        setattr(pre_item, k, v)
                        pre_item.save()
            else:
                OrderItem.objects.create(**filter_data, **update_data)

    order_items = property(_get_order_items, _set_order_items)

    class Meta:
        ordering = ['-id']
        verbose_name = _('销售订单')
        verbose_name_plural = verbose_name

    def __str__(self):
        return '{0}'.format(self.order_number)


@receiver(pre_save, sender=ProductSalesOrder)
def pre_save_product_sales_order(sender, instance, **kwargs):
    """
    保存前自动创建订单号
    """
    instance.make_order_number()
    instance.update_order_state()


class OrderItem(models.Model):
    product_sales_order = models.ForeignKey(
        ProductSalesOrder,
        on_delete=models.CASCADE,
        verbose_name=_('销售订单')
    )
    product_sales = models.ForeignKey(
        'product.ProductSales',
        on_delete=models.PROTECT,
        verbose_name=_('在售商品')
    )
    vip_level = models.ForeignKey(
        'vip.VipLevel',
        on_delete=models.PROTECT,
        null=True,
        blank=True,
        verbose_name=_('会员等级')
    )
    amount = models.IntegerField(verbose_name='数量', default=1)
    price_initial = models.DecimalField(
        verbose_name='产品单价', null=True, blank=True, max_digits=12, decimal_places=2)
    price_payed = models.DecimalField(
        verbose_name='产品单价-支付', null=True, blank=True, max_digits=12, decimal_places=2)

    objects = models.Manager()

    def update_product_sales(self):
        # 更新在售商品的当前销售数量
        from product.models import ProductSales
        sales_data = OrderItem.objects.filter(
            product_sales_id=self.product_sales_id,
            product_sales_order__is_show=True
        ).aggregate(
            amount_sales=Sum('amount')
        )
        if sales_data:
            amount_sales = int_value(sales_data['amount_sales'])
            product_sales = ProductSales.objects.get(pk=self.product_sales_id)

            product_sales.current_sales = amount_sales
            product_sales.save()
            print('product_sales.save()', datetime.datetime.now(), self.product_sales_id, amount_sales)
        # 更新用户购买数量
        if self.vip_level:
            from vip.models import VipSalesOrder
            related_vip_sales_order = VipSalesOrder.objects.filter(
                user_id=self.product_sales_order.user_id,
                is_payed=True,
                vip_sales__vip_start__lte=self.product_sales_order.datetime_created,
                vip_sales__vip_end__gte=self.product_sales_order.datetime_created,
                vip_sales__vip_level_id=self.vip_level_id
            ).order_by('pk').first()
            if related_vip_sales_order:
                related_vip_sales_order.amount_used = related_vip_sales_order.get_amount_used()
                related_vip_sales_order.save()

    class Meta:
        ordering = ['-id']
        verbose_name = _('订单明细')
        verbose_name_plural = verbose_name

    def __str__(self):
        return '{0}'.format(self.product_sales_order)


@receiver(post_save, sender=OrderItem)
def post_save_order_item(sender, instance, **kwargs):
    instance.update_product_sales()
